package org.xx.sipahi;

import java.util.Date;
import java.util.Objects;

import static org.apache.commons.io.FilenameUtils.getExtension;
import static org.apache.commons.lang3.StringUtils.trimToEmpty;

/**
 * 文件引用。
 */
public final class FileRef {
    public static final long K_BYTES = 1024;
    public static final long M_BYTES = 1024 * K_BYTES;
    public static final long G_BYTES = 1024 * M_BYTES;

    private final String name;
    private final String path;
    private final long size;
    private final long lastModified;
    private final boolean directory;

    /**
     * 构造文件对象。
     *
     * @param name
     *         文件名。
     * @param path
     *         文件的路径，一定以斜线开头，是相对于根路径的路径。
     * @param size
     *         文件的长度。
     * @param lastModified
     *         文件的最后修改日期。
     * @param directory
     *         此文件对象是否表示目录。
     */
    public FileRef(
            String name,
            String path,
            long size,
            long lastModified,
            boolean directory
    ) {
        name = trimToEmpty(name);
        if (name.isEmpty()) {
            throw new IllegalArgumentException("argument \"name\" cannot be null or empty");
        }
        path = trimToEmpty(path);
        if (path.isEmpty()) {
            throw new IllegalArgumentException("argument \"path\" cannot be null or empty");
        }
        if (!path.startsWith("/")) {
            throw new IllegalArgumentException("argument \"path\" must start with /");
        }

        this.name = name;
        this.path = path;
        this.size = size;
        this.lastModified = lastModified;
        this.directory = directory;
    }

    /**
     * 获取文件名。
     *
     * @return 文件名。
     */
    public String getName() {
        return this.name;
    }

    /**
     * 获取文件的路径。
     *
     * @return 文件的路径，一定以斜线开头，是相对于根路径的路径。
     */
    public String getPath() {
        return this.path;
    }

    /**
     * 获取文件的扩展名。
     *
     * @return 文件的扩展名。
     */
    public String getExt() {
        return "." + getExtension(this.name).toLowerCase();
    }

    /**
     * 获取文件长度。
     *
     * @return 文件长度。
     */
    public long getSize() {
        return this.size;
    }

    /**
     * 获取可读的文件长度。
     *
     * @return 可读的文件长度。
     */
    public String getReadableSize() {
        if (this.size < 10 * K_BYTES) {
            return this.size + " Bytes";
        } else if (this.size < 10 * M_BYTES) {
            return this.size / 1024 + " KB";
        } else if (this.size < 10 * G_BYTES) {
            return this.size / (1024 * 1024) + " MB";
        } else {
            return this.size / (1024 * 1024 * 1024) + " GB";
        }
    }

    /**
     * 获取文件的最后修改日期。
     *
     * @return 文件的最后修改日期。
     */
    public Date getLastModified() {
        return new Date(this.lastModified);
    }

    /**
     * 判断此文件对象是否表示目录。
     *
     * @return 此文件对象是否表示目录。
     */
    public boolean isDirectory() {
        return this.directory;
    }

    @Override
    public int hashCode() {
        return Objects.hash(this.name, this.path, this.size, this.lastModified, this.directory);
    }

    @Override
    public boolean equals(
            Object obj
    ) {
        if (obj == this) {
            return true;
        }
        if (!(obj instanceof FileRef)) {
            return false;
        }
        final FileRef other = (FileRef) obj;
        return this.size == other.size
                && this.lastModified == other.lastModified
                && this.directory == other.directory
                && Objects.equals(this.name, other.name)
                && Objects.equals(this.path, other.path);
    }

    @Override
    public String toString() {
        return "FileRef(" +
                "name='" + this.name + '\'' +
                ",path='" + this.path + '\'' +
                ",size=" + this.size +
                ",lastModified=" + this.lastModified +
                ",directory=" + this.directory +
                ')';
    }
}
